package com.societyGames.flashForms
{
import com.societyGames.system.EventObject;

import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.MouseEvent;

/**
 * ...
 * @author ...
 */
public class ExpanderHeaderContainer extends SingleItemContainer
{
  private var _currentIndicator:DisplayObject;				//The indicator in the header.
  private var _currentIndicatorOriginalWidth:Number;	//The original size of the indicator.
  private var _currentIndicatorOriginalHeight:Number;
  private var _collapsedIndicator:DisplayObject;				//Graphics for indicators
  private var _expandedIndicator:DisplayObject;
  private var _collapsedOverIndicator:DisplayObject;
  private var _expandedOverIndicator:DisplayObject;

  private var _desiredWidth:Number;					//How wide we should be set to.
  private var _desiredHeight:Number;
  private var _sizeChangedEventObject:EventObject;
  private var _isExpandedChangedEventObject:EventObject;
  private var _isExpanded:Boolean;			//Whether the expander is expanded.
  private var _isMouseOver:Boolean;
  private var _childOriginalHeight:Number;

  public function ExpanderHeaderContainer(collapsed:DisplayObject, expanded:DisplayObject, collapsedOver:DisplayObject = null, expandedOver:DisplayObject = null)
  {
    this._sizeChangedEventObject = new EventObject(this, "SIZE_CHANGED", Event);
    this._isExpandedChangedEventObject = new EventObject(this, "CLICK", Event);

    this.addEventListener(MouseEvent.CLICK, clickHandler);
    this.addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);
    this.addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);

    this._collapsedIndicator = collapsed;
    this._collapsedIndicator.visible = false;
    this.addChild(this._collapsedIndicator);

    this._expandedIndicator = expanded;
    this._expandedIndicator.visible = false;
    this.addChild(this._expandedIndicator);

    this._collapsedOverIndicator = collapsedOver;
    if (this._collapsedOverIndicator != null)
    {
      this._collapsedOverIndicator.visible = false;
      this.addChild(this._collapsedOverIndicator);
    }

    this._expandedOverIndicator = expandedOver;
    if (this._expandedOverIndicator != null)
    {
      this._expandedOverIndicator.visible = false;
      this.addChild(this._expandedOverIndicator);
    }

    this.useHandCursor = true;
    this.buttonMode = true;

    this._isExpanded = false;
    this._isMouseOver = false;
    //Set everything up.
    recalculate();
  }

  public function get isExpanded():Boolean
  {
    return this._isExpanded;
  }

  public function set isExpanded(value:Boolean):void
  {
    if (value != this._isExpanded)
    {
      this._isExpanded = value;
      recalculate();
      this._isExpandedChangedEventObject.dispatchEvent();
    }
  }

  public function get sizeChangedEventObject():EventObject
  {
    return this._sizeChangedEventObject;
  }

  public function get isExpandedChangedEventObject():EventObject
  {
    return this._isExpandedChangedEventObject;
  }

  public override function set height(value:Number):void
  {
    if (value != this._desiredHeight)
    {
      this._desiredHeight = value;
      recalculateHeight();
    }
  }

  public override function set width(value:Number):void
  {
    if (value != this._desiredWidth)
    {
      this._desiredWidth = value;
      recalculate();
    }
  }

  public override function set item(value:DisplayObject):void
  {
    //Store the original height before any recalculation happens.
    if (value != null)
    {
      this._childOriginalHeight = value.height;
    }
    //Store it normally.
    super.item = value;
  }

  override protected function childSizeChangedHandler(event:Event):void
  {
    super.childSizeChangedHandler(event);
    recalculate();
  }

  public function get desiredHeight():Number
  {
    return Math.max(this._currentIndicatorOriginalHeight, this._childOriginalHeight);
  }

  private function clickHandler(event:MouseEvent):void
  {
    this.isExpanded = !this._isExpanded;
  }


  private function rollOverHandler(event:MouseEvent):void
  {
    this._isMouseOver = true;
    recalculate();
  }

  private function rollOutHandler(event:MouseEvent):void
  {
    this._isMouseOver = false;
    recalculate();
  }

  private function recalculate():void
  {
    var oldWidth:Number = this.width;
    var oldHeight:Number = this.height;

    //Choose an indicator
    var newIndicator:DisplayObject;
    if (this._isExpanded)
    {
      if (this._isMouseOver && this._expandedOverIndicator != null)
      {
        newIndicator = this._expandedOverIndicator;
      }
      else
      {
        newIndicator = this._expandedIndicator;
      }
    }
    else //Not expanded
    {
      if (this._isMouseOver && this._collapsedOverIndicator != null)
      {
        newIndicator = this._collapsedOverIndicator;
      }
      else
      {
        newIndicator = this._collapsedIndicator;
      }
    }
    if (newIndicator != this._currentIndicator)
    {
      if (this._currentIndicator != null)
      {
        //Remove old indicator.
        this._currentIndicator.width = this._currentIndicatorOriginalWidth;
        this._currentIndicator.height = this._currentIndicatorOriginalHeight;
        this._currentIndicator.visible = false;
      }
      //Set new indicator.
      this._currentIndicator = newIndicator;
      this._currentIndicatorOriginalWidth = this._currentIndicator.width;
      this._currentIndicatorOriginalHeight = this._currentIndicator.height;
      this._currentIndicator.visible = true;
    }

    //Calculate the width
    if (this._currentIndicatorOriginalWidth < this._desiredWidth) ////Both header and indicator should fit horizontally.
    {
      this._currentIndicator.width = this._currentIndicatorOriginalWidth;
      //Let the header take the rest.
      if (this._item != null)
      {
        this._item.x = this._currentIndicator.x + this._currentIndicator.width;
        this._item.width = this._desiredWidth - this._currentIndicator.width;
      }
    }
    else
    {
      this._currentIndicator.width = this._desiredWidth;
      if (this._item != null)
      {
        this._item.x = this._currentIndicator.x + this._currentIndicator.width;
        this._item.width = 0;
      }
    }

    recalculateHeight();

    if (oldWidth != this.width || oldHeight != this.height)
    {
      this._sizeChangedEventObject.dispatchEvent();
    }
  }

  private function recalculateHeight():void
  {
    centerOrScaleVertically(this._currentIndicator, this._currentIndicatorOriginalHeight);
    if (this._item != null)
    {
      trace("Original height: " + this._childOriginalHeight);
      trace("Desired height: " + this._desiredHeight);
      centerOrScaleVertically(this._item, this._childOriginalHeight);
      trace("Choice: " + this._item.height);
    }
  }

  private function centerOrScaleVertically(displayObject:DisplayObject, displayObjectDefaultHeight:Number):void
  {
    if (this._desiredHeight < displayObjectDefaultHeight)
    {
      displayObject.y = 0;
      displayObject.height = this._desiredHeight;
    }
    else
    {
      displayObject.height = displayObjectDefaultHeight;
      displayObject.y = (this._desiredHeight - displayObject.height) / 2;
    }
  }
}
}